package plgloader

import (
	"fmt"
	"gitee.com/ymofen/gobase"
	"gitee.com/ymofen/golang/refobjects"
)

type RefObjectWrapper struct {
	config       string
	objRef       *refobjects.RefWrapper
	releaseFuncs *gobase.SyncFuncList
}

func NewRefObjectWrapper() *RefObjectWrapper {
	return &RefObjectWrapper{releaseFuncs: gobase.NewSyncFuncList()}
}

func (this *RefObjectWrapper) releasePre() {
	if this.objRef != nil {
		this.releaseFuncs.ExecuteAndRemoveAll()
		this.objRef.Close()
		this.objRef = nil
	}
}

func (this *RefObjectWrapper) Close() error {
	this.releasePre()
	return nil
}

func (this *RefObjectWrapper) ReadValue(args ...interface{}) (v interface{}, err error) {
	if this.objRef == nil {
		return nil, fmt.Errorf("invalid objRef")
	}
	rd, ok := this.objRef.Object.(ValueReader)
	if ok {
		return rd.ReadValue(args...)
	}
	return
}

// 重复执行会被覆盖
func (this *RefObjectWrapper) TryAddLs(cb func(topic string, args ...interface{})) (ok bool, err error) {
	if this.objRef == nil {
		return false, fmt.Errorf("invalid objRef")
	}

	rd, ok := this.objRef.Object.(DataListener)
	if !ok {
		return false, nil
	}

	this.releaseFuncs.Execute("ls")

	hd, err := rd.Subscribe(cb)
	if err != nil {
		return false, err
	} else {
		this.releaseFuncs.AddOrSet("ls", func(args ...interface{}) {
			rd.CancelSubscribe(hd)
		})
	}
	return true, nil
}

func (this *RefObjectWrapper) UpdateConfig(s string) (changed bool, err error) {
	if this.config == s {
		return false, nil
	}
	this.releasePre()

	this.config = s
	if len(s) == 0 {
		return true, nil
	}

	objRef, err := refobjects.Acquire(this.config)
	if err != nil {
		return true, err
	}
	this.objRef = objRef
	return true, nil
}

type ValueReader interface {
	ReadValue(args ...interface{}) (v interface{}, err error)
}

type DataListener interface {
	Subscribe(cb func(topic string, args ...interface{})) (subHandle interface{}, err error)
	CancelSubscribe(subHandle interface{}) (err error)
}
